<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="cache-control" content="no-cache">
<title>Genivia - WS-Security lite</title>
<link href="genivia_tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="genivia_content.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="top">
 <div id="titlearea">
  <table height="72px" width="100%" cellspacing="0" cellpadding="0">
   <tbody>
    <tr>
     <td width="10%">&nbsp;</td>
     <td width="175px"><a href="https://www.genivia.com"><img alt="Genivia" src="GeniviaLogo2_trans_noslogan.png"/></a></td>
     <td class="tab_home"><a href="https://www.genivia.com">Home</a></td>
     <td class="tab_home"><a href="https://www.genivia.com/docs.html">Documentation</a></td>
     <td>
      <div style="float: right; font-size: 18px; font-weight: bold;">WS-Security lite</div>
      <br>
      <div style="float: right; font-size: 10px;">updated Fri Jul 17 2020 by Robert van Engelen</div>
     </td>
     <td width="10%">&nbsp;</td>
    </tr>
   </tbody>
  </table>
 </div>
<!-- Generated by Doxygen 1.8.11 -->
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
    </ul>
  </div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">WS-Security lite </div>  </div>
</div><!--header-->
<div class="contents">
<div class="toc"><h3>Table of Contents</h3>
<ul><li class="level1"><a href="#wsse_5">Security Header</a></li>
<li class="level1"><a href="#wsse_6">Security Tokens</a><ul><li class="level2"><a href="#wsse_6_2">User Name Token</a></li>
</ul>
</li>
<li class="level1"><a href="#wsse_10">Security Timestamps</a></li>
<li class="level1"><a href="#wsse_11">WS-Security and HTTPS</a></li>
</ul>
</div>
<div class="textblock"><h1><a class="anchor" id="wsse_5"></a>
Security Header</h1>
<p>The material in this section relates to the WS-Security specification section 5.</p>
<p>To use the wsse lite API:</p><ol type="1">
<li>Run wsdl2h -t typemap.dat on a WSDL of a service that requires WS-Security headers. The typemap.dat file is used to recognize and translate Security header blocks.</li>
<li>Run soapcpp2 on the header file produced by wsdl2h.</li>
<li>Use the wsse lite API functions described below to add time stamp and user name tokens.</li>
</ol>
<p>If HTTPS is required with OpenSSL then please follow the instructions in Section <a class="el" href="wsse.html#wsse_11">WS-Security and HTTPS</a> to ensure thread-safety of WS-Security with HTTPS.</p>
<p>The wsse lite API is located in:</p>
<ul>
<li><code><a class="el" href="wsseapi-lite_8h.html">gsoap/plugin/wsseapi-lite.h</a></code> wsse lite API.</li>
<li><code><a class="el" href="wsseapi-lite_8c.html">gsoap/plugin/wsseapi-lite.c</a></code> wsse lite API for C and C++.</li>
</ul>
<p>You will also need:</p>
<ul>
<li><code>gsoap/custom/struct_timeval.c</code> compile and link this file (C and C++).</li>
<li>compile all sources with <code>-DWITH_OPENSSL</code> to enable HTTPS.</li>
<li>if you have zlib installed, compile all sources also with <code>-DWITH_GZIP</code>.</li>
<li>link with <code>-lssl -lcrypto -lz -gsoapssl++</code> (or <code>-lgsoapssl</code> for C, or compile <code>stdsoap2.cpp</code> for C++ and <code>stdsoap2.c</code> for C).</li>
</ul>
<p>The gSOAP header file for soapcpp2 should import <a class="el" href="wsse_8h.html">wsse.h</a> (or the older 2002 version wsse2.h):</p>
<div class="fragment"><div class="line"><span class="preprocessor">#import &quot;<a class="code" href="wsse_8h.html">wsse.h</a>&quot;</span></div></div><!-- fragment --><p>The wsdl2h tool adds the necessary imports to the generated header file if the WSDL declares the use of WS-Security. If not, you may have to add the import manually before running soapcpp2.</p>
<p>The wsse lite API consists of a set of functions to populate and verify WS-Security headers and message body content. For more details, we refer to the following sections that correspond to the WS-Security specification sections:</p>
<ul>
<li>Section 6 <a class="el" href="wsse.html#wsse_6">Security Tokens</a></li>
<li>Section 10 <a class="el" href="wsse.html#wsse_10">Security Timestamps</a></li>
<li><a class="el" href="wsse.html#wsse_11">WS-Security and HTTPS</a></li>
</ul>
<p>The basic API is introduced below.</p>
<p>To add an empty Security header block to the SOAP header, use:</p>
<div class="fragment"><div class="line"><a class="code" href="wsseapi-lite_8h.html#acdc56c76c1a39c3e6191580d491f9b8e">soap_wsse_add_Security</a>(soap);</div></div><!-- fragment --><p>To delete a Security header, use:</p>
<div class="fragment"><div class="line"><a class="code" href="wsseapi-lite_8h.html#ac06c7021592b2aaca50f73e0de9dec7c">soap_wsse_delete_Security</a>(soap);</div></div><!-- fragment --><p>Adding an empty Security header block is not very useful. In the following, we present the higher-level functions of the wsse lite API to populate and verify Security header content.</p>
<dl class="section note"><dt>Note</dt><dd>The soap context includes an actor value soap.actor that is populated and rendered as the SOAP-ENV:actor (SOAP 1.1) or SOAP-ENV:role (SOAP 1.2) attribute in XML within the generic SOAP Header. The attribute is optional, but should be used to target a recipient such as an intermediate node to process the SOAP header. In contrast, actor or role attributes within Security header blocks target specific recipients to process the Security header block. The gSOAP implementation does not automate this feature and application should set and check the actor/role attribute when necessary. In addition, the current implementation supports the inclusion of a single Security header block in the SOAP header.</dd></dl>
<p>To populate the SOAP-ENV:actor or SOAP-ENV:role attribute within the Security header, use:</p>
<div class="fragment"><div class="line"><a class="code" href="wsseapi-lite_8h.html#a16b318c7c4e19d55a07503d72b49e0d7">soap_wsse_add_Security_actor</a>(soap, <span class="stringliteral">&quot;recipient&quot;</span>);</div></div><!-- fragment --><p>To obtain the actor or role value (e.g. after receiving a message), use:</p>
<div class="fragment"><div class="line"><a class="code" href="struct__wsse_____security.html">_wsse__Security</a> *security = <a class="code" href="wsseapi-lite_8h.html#ae7775b49a0cd57c7cf85db7bb18b034d">soap_wsse_Security</a>(soap);</div><div class="line"><span class="keywordflow">if</span> (security)</div><div class="line">{</div><div class="line">  ... = security-&gt;<a class="code" href="struct__wsse_____security.html#a1a941d6f69eab871bced7acdb6eb41f3">SOAP_ENV__actor</a>; <span class="comment">// SOAP 1.1</span></div><div class="line">  ... = security-&gt;<a class="code" href="struct__wsse_____security.html#a86e02ae8da9bf2f6e1dd6eda8f596012">SOAP_ENV__role</a>;  <span class="comment">// SOAP 1.2</span></div></div><!-- fragment --><p>The SOAP-ENV:mustUnderstand attribute is automatically added and checked by the gSOAP engine. A gSOAP application compiled without Security support will reject Security headers.</p>
<p>Security header blocks are attached to the soap context, which means that the information will be automatically kept to support multiple invocations.</p>
<h1><a class="anchor" id="wsse_6"></a>
Security Tokens</h1>
<p>The material in this section relates to the WS-Security specification section 6.</p>
<h2><a class="anchor" id="wsse_6_2"></a>
User Name Token</h2>
<p>To add a user name token to the Security header block, use:</p>
<div class="fragment"><div class="line"><a class="code" href="wsseapi-lite_8h.html#a37f32e51bceabf2e2823516a1737548f">soap_wsse_add_UsernameTokenText</a>(soap, <span class="stringliteral">&quot;Id&quot;</span>, <span class="stringliteral">&quot;username&quot;</span>, NULL);</div></div><!-- fragment --><p>The <code>Id</code> value is optional and not used in the wsse lite API. These <code>Id</code>s are serialized as wsu:Id identifiers for cross-referencing XML elements.</p>
<p>To add a user name token with clear text password, use:</p>
<div class="fragment"><div class="line"><a class="code" href="wsseapi-lite_8h.html#a37f32e51bceabf2e2823516a1737548f">soap_wsse_add_UsernameTokenText</a>(soap, <span class="stringliteral">&quot;Id&quot;</span>, <span class="stringliteral">&quot;username&quot;</span>, <span class="stringliteral">&quot;password&quot;</span>);</div></div><!-- fragment --><p>It is strongly recommended to use <code>soap_wsse_add_UsernameTokenText</code> only in combination with HTTPS encrypted transmission or not at all. A better alternative is to use password digests (not supported in this wsse lite API).</p>
<p>Clear-text passwords are verified with <code>soap_wsse_verify_Password</code>. To verify a password at the receiving side to authorize a request (e.g. within a Web service operation), use:</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> ns__myMethod(<span class="keyword">struct</span> soap *soap, ...)</div><div class="line">{</div><div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span> *username = <a class="code" href="wsseapi-lite_8h.html#aca3fe6fb7c1e5c103827b33f24292f47">soap_wsse_get_Username</a>(soap);</div><div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span> *password;</div><div class="line">  <span class="keywordflow">if</span> (!username)</div><div class="line">    <span class="keywordflow">return</span> soap-&gt;error; <span class="comment">// no username: return FailedAuthentication (from soap_wsse_get_Username)</span></div><div class="line">  password = ...; <span class="comment">// lookup password of username</span></div><div class="line">  <span class="keywordflow">if</span> (<a class="code" href="wsseapi-lite_8h.html#aeb0afd01a5036e4f1314a3cfe8575bd5">soap_wsse_verify_Password</a>(soap, password))</div><div class="line">  {</div><div class="line">    <span class="keywordtype">int</span> err = soap-&gt;error;</div><div class="line">    <a class="code" href="wsseapi-lite_8h.html#ac06c7021592b2aaca50f73e0de9dec7c">soap_wsse_delete_Security</a>(soap); <span class="comment">// remove old security headers</span></div><div class="line">    <span class="keywordflow">return</span> err; <span class="comment">// password verification failed: return FailedAuthentication</span></div><div class="line">  }</div><div class="line">  <span class="keywordflow">return</span> SOAP_OK;</div><div class="line">}</div></div><!-- fragment --><p>Note that the <code>soap_wsse_get_Username</code> functions sets the wsse:FailedAuthentication fault upon failure. It is common for the API functions functions to return SOAP_OK or a wsse fault that should be passed to the sender by returning soap-&gt;error from service operations. The fault is displayed with the <code>soap_print_fault</code> function.</p>
<h1><a class="anchor" id="wsse_10"></a>
Security Timestamps</h1>
<p>The material in this section relates to the WS-Security specification section 10.</p>
<p>To add a timestamp with the creation time to the Security header, use:</p>
<div class="fragment"><div class="line"><a class="code" href="wsseapi-lite_8h.html#a71fe27aee76db1d0a635afe106d8b109">soap_wsse_add_Timestamp</a>(soap, NULL, 0); <span class="comment">// no expiration</span></div></div><!-- fragment --><p>The lifetime of a message (in seconds) is passed as the third argument, which will be displayed as the timestamp expiration time:</p>
<div class="fragment"><div class="line"><a class="code" href="wsseapi-lite_8h.html#a71fe27aee76db1d0a635afe106d8b109">soap_wsse_add_Timestamp</a>(soap, NULL, 10); <span class="comment">// 10 seconds lifetime</span></div></div><!-- fragment --><h1><a class="anchor" id="wsse_11"></a>
WS-Security and HTTPS</h1>
<p>HTTPS is used at the client side with the usual "https:" URL addressing, shown here:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="wsseapi-lite_8h.html">wsseapi-lite.h</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;threads.h&quot;</span></div><div class="line"><span class="keyword">struct </span>soap *soap;</div><div class="line"><span class="keywordflow">if</span> (CRYPTO_thread_setup())</div><div class="line">  ... <span class="comment">// error</span></div><div class="line">soap = soap_new1(SOAP_XML_CANONICAL | SOAP_XML_INDENT);</div><div class="line"><span class="keywordflow">if</span> (soap_ssl_client_context(&amp;soap,</div><div class="line">  SOAP_SSL_DEFAULT, <span class="comment">// requires server authentication</span></div><div class="line">  NULL,             <span class="comment">// keyfile for client authentication to server</span></div><div class="line">  NULL,             <span class="comment">// the keyfile password</span></div><div class="line">  <span class="stringliteral">&quot;cacerts.pem&quot;</span>,    <span class="comment">// cafile CA certificates to authenticate the server</span></div><div class="line">  NULL,             <span class="comment">// capath CA directory path to certificates</span></div><div class="line">  NULL</div><div class="line">))</div><div class="line">  ... <span class="comment">// error</span></div><div class="line">soap-&gt;cafile = <span class="stringliteral">&quot;cacerts.pem&quot;</span>;  <span class="comment">// same as above (or overrides the above)</span></div><div class="line">soap-&gt;capath = <span class="stringliteral">&quot;dir/to/certs&quot;</span>; <span class="comment">// and/or point to CA certs</span></div><div class="line">soap-&gt;crlfile = <span class="stringliteral">&quot;revoked.pem&quot;</span>; <span class="comment">// use CRL (optional)</span></div><div class="line"><a class="code" href="wsseapi-lite_8h.html#ac06c7021592b2aaca50f73e0de9dec7c">soap_wsse_delete_Security</a>(soap); <span class="comment">// remove any previous header content</span></div><div class="line"><a class="code" href="wsseapi-lite_8h.html#a37f32e51bceabf2e2823516a1737548f">soap_wsse_add_UsernameTokenText</a>(soap, NULL, <span class="stringliteral">&quot;username&quot;</span>, <span class="stringliteral">&quot;password&quot;</span>);</div><div class="line"><a class="code" href="wsseapi-lite_8h.html#a71fe27aee76db1d0a635afe106d8b109">soap_wsse_add_Timestamp</a>(soap, NULL, 10); <span class="comment">// 10 seconds lifetime</span></div><div class="line"><span class="keywordflow">if</span> (soap_call_ns__myMethod(soap, <span class="stringliteral">&quot;https://...&quot;</span>, ...))</div><div class="line">  ... <span class="comment">// error</span></div><div class="line">... <span class="comment">// process response results</span></div><div class="line">soap_destroy(soap);</div><div class="line">soap_end(soap);</div><div class="line">soap_free(soap);</div><div class="line">CRYPTO_thread_cleanup();</div></div><!-- fragment --><p>With OpenSSL, the CRYPTO threads should be set up before any threads are created.</p>
<p>The <code>soap_ssl_client_context</code> only needs to be set up once. Use the following flags:</p>
<ul>
<li><code>SOAP_SSL_DEFAULT</code> requires server authentication, CA certs should be used</li>
<li><code>SOAP_SSL_NO_AUTHENTICATION</code> disables server authentication</li>
<li><code>SOAP_SSL_SKIP_HOST_CHECK</code> disables server authentication host check</li>
<li><code>SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE</code> to accept self-signed certificates, expired certificates, and certificates without CRL.</li>
</ul>
<p>The server uses the following:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="wsseapi-lite_8h.html">wsseapi-lite.h</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;threads.h&quot;</span></div><div class="line">SOAP_SOCKET m, s;</div><div class="line"><span class="keywordtype">int</span> port = 443;</div><div class="line"><span class="keyword">struct </span>soap *soap;</div><div class="line"><span class="keywordflow">if</span> (CRYPTO_thread_setup())</div><div class="line">  ... <span class="comment">// error</span></div><div class="line">soap = soap_new1(SOAP_XML_CANONICAL | SOAP_XML_INDENT);</div><div class="line"><span class="keywordflow">if</span> (soap_ssl_server_context(&amp;soap,</div><div class="line">  SOAP_SSL_DEFAULT, <span class="comment">// requires server to authenticate, but not the client</span></div><div class="line">  server.pem,       <span class="comment">// keyfile for authentication to client</span></div><div class="line">  <span class="stringliteral">&quot;password&quot;</span>,       <span class="comment">// the keyfile password</span></div><div class="line">  NULL,             <span class="comment">// CA certificates to authenticate the client</span></div><div class="line">  NULL,             <span class="comment">// CA directory path to certificates</span></div><div class="line">  NULL,             <span class="comment">// use RSA 2048 bits (or give file name with DH param)</span></div><div class="line">  NULL,</div><div class="line">  NULL</div><div class="line">))</div><div class="line">  ... <span class="comment">// error</span></div><div class="line"><span class="keywordflow">if</span> (!soap_valid_socket(m = soap_bind(soap, NULL, port, 100))</div><div class="line">  ... <span class="comment">// error</span></div><div class="line"><span class="keywordflow">for</span> (;;)</div><div class="line">{</div><div class="line">  <span class="keywordflow">if</span> (!soap_valid_socket(s = soap_accept(soap)))</div><div class="line">    ... <span class="comment">// error</span></div><div class="line">  <span class="keywordflow">else</span></div><div class="line">  {</div><div class="line">    <span class="keyword">struct </span>soap *tsoap = soap_copy(soap);</div><div class="line">    <span class="keywordflow">while</span> (THREAD_CREATE(&amp;tid, (<span class="keywordtype">void</span>*(*)(<span class="keywordtype">void</span>*))&amp;process_request, (<span class="keywordtype">void</span>*)tsoap))</div><div class="line">      sleep(1);</div><div class="line">  }</div><div class="line">}</div><div class="line">soap_destroy(soap);</div><div class="line">soap_end(soap);</div><div class="line">soap_free(soap);</div><div class="line">CRYPTO_thread_cleanup();</div></div><!-- fragment --><p>where we define a process_request function that is executed by the thread to process the request (on a copy of the soap context struct):</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> *process_request(<span class="keyword">struct</span> soap *soap)</div><div class="line">{</div><div class="line">  <span class="keywordflow">if</span> (soap_ssl_accept(soap)</div><div class="line">   || soap_serve(soap))</div><div class="line">    ... <span class="comment">// error</span></div><div class="line">  soap_destroy(soap);</div><div class="line">  soap_end(soap);</div><div class="line">  soap_free(soap);</div><div class="line">}</div></div><!-- fragment --><p>The <code>soap_ssl_server_context</code> only needs to be set up once. Use the following flags:</p>
<ul>
<li><code>SOAP_SSL_DEFAULT</code> requires server authentication, but no client authentication</li>
<li><code>SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION</code> requires client authentication</li>
</ul>
<p>With OpenSSL, we need to define the thread set up and clean up operations as follows:</p>
<div class="fragment"><div class="line"><span class="keyword">struct </span>CRYPTO_dynlock_value</div><div class="line">{</div><div class="line">  MUTEX_TYPE mutex;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">static</span> MUTEX_TYPE *mutex_buf;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>CRYPTO_dynlock_value *dyn_create_function(<span class="keyword">const</span> <span class="keywordtype">char</span> *file, <span class="keywordtype">int</span> line)</div><div class="line">{</div><div class="line">  <span class="keyword">struct </span>CRYPTO_dynlock_value *value;</div><div class="line">  value = (<span class="keyword">struct </span>CRYPTO_dynlock_value*)malloc(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> CRYPTO_dynlock_value));</div><div class="line">  <span class="keywordflow">if</span> (value)</div><div class="line">    MUTEX_SETUP(value-&gt;mutex);</div><div class="line">  <span class="keywordflow">return</span> value;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> dyn_lock_function(<span class="keywordtype">int</span> mode, <span class="keyword">struct</span> CRYPTO_dynlock_value *l, <span class="keyword">const</span> <span class="keywordtype">char</span> *file, <span class="keywordtype">int</span> line)</div><div class="line">{</div><div class="line">  <span class="keywordflow">if</span> (mode &amp; CRYPTO_LOCK)</div><div class="line">    MUTEX_LOCK(l-&gt;mutex);</div><div class="line">  <span class="keywordflow">else</span></div><div class="line">    MUTEX_UNLOCK(l-&gt;mutex);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> dyn_destroy_function(<span class="keyword">struct</span> CRYPTO_dynlock_value *l, <span class="keyword">const</span> <span class="keywordtype">char</span> *file, <span class="keywordtype">int</span> line)</div><div class="line">{</div><div class="line">  MUTEX_CLEANUP(l-&gt;mutex);</div><div class="line">  free(l);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> locking_function(<span class="keywordtype">int</span> mode, <span class="keywordtype">int</span> n, <span class="keyword">const</span> <span class="keywordtype">char</span> *file, <span class="keywordtype">int</span> line)</div><div class="line">{</div><div class="line">  <span class="keywordflow">if</span> (mode &amp; CRYPTO_LOCK)</div><div class="line">    MUTEX_LOCK(mutex_buf[n]);</div><div class="line">  <span class="keywordflow">else</span></div><div class="line">    MUTEX_UNLOCK(mutex_buf[n]);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> id_function()</div><div class="line">{</div><div class="line">  <span class="keywordflow">return</span> (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)THREAD_ID;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> CRYPTO_thread_setup()</div><div class="line">{</div><div class="line">  <span class="keywordtype">int</span> i;</div><div class="line">  mutex_buf = (MUTEX_TYPE*)malloc(CRYPTO_num_locks() * <span class="keyword">sizeof</span>(pthread_mutex_t));</div><div class="line">  <span class="keywordflow">if</span> (!mutex_buf)</div><div class="line">    <span class="keywordflow">return</span> SOAP_EOM;</div><div class="line">  <span class="keywordflow">for</span> (i = 0; i &lt; CRYPTO_num_locks(); i++)</div><div class="line">    MUTEX_SETUP(mutex_buf[i]);</div><div class="line">  CRYPTO_set_id_callback(id_function);</div><div class="line">  CRYPTO_set_locking_callback(locking_function);</div><div class="line">  CRYPTO_set_dynlock_create_callback(dyn_create_function);</div><div class="line">  CRYPTO_set_dynlock_lock_callback(dyn_lock_function);</div><div class="line">  CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);</div><div class="line">  <span class="keywordflow">return</span> SOAP_OK;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> CRYPTO_thread_cleanup()</div><div class="line">{</div><div class="line">  <span class="keywordtype">int</span> i;</div><div class="line">  <span class="keywordflow">if</span> (!mutex_buf)</div><div class="line">    <span class="keywordflow">return</span>;</div><div class="line">  CRYPTO_set_id_callback(NULL);</div><div class="line">  CRYPTO_set_locking_callback(NULL);</div><div class="line">  CRYPTO_set_dynlock_create_callback(NULL);</div><div class="line">  CRYPTO_set_dynlock_lock_callback(NULL);</div><div class="line">  CRYPTO_set_dynlock_destroy_callback(NULL);</div><div class="line">  <span class="keywordflow">for</span> (i = 0; i &lt; CRYPTO_num_locks(); i++)</div><div class="line">    MUTEX_CLEANUP(mutex_buf[i]);</div><div class="line">  free(mutex_buf);</div><div class="line">  mutex_buf = NULL;</div><div class="line">}</div></div><!-- fragment --><p>For additional details and examples, see the user guide and examples in the gSOAP package directory <code>gsoap/samples/ssl</code>. </p>
</div></div><!-- contents -->
<hr class="footer">
<address class="footer">
Copyright (C) 2020, Robert van Engelen, Genivia Inc., All Rights Reserved.
</address>
<address class="footer"><small>
Converted on Fri Jul 17 2020 08:49:24 by <a target="_blank" href="http://www.doxygen.org/index.html">Doxygen</a> 1.8.11</small></address>
<br>
<div style="height: 246px; background: #DBDBDB;">
</body>
</html>
